<?php

Raise::load('core.RaiseObject');
Raise::load('core.IRaiseCache');
Raise::load('core.RaiseTimeSpan');
Raise::load('core.RaisePath');
Raise::load('core.RaiseFileSystem');
Raise::load('core.RaiseFile');
Raise::load('core.RaiseHashDigest');

/**
 * RaiseCache class
 * provides in-house caching on file system
 * 
 * @author Sam-Mauris Yong <hellclanner at live dot com>
 * @license http://www.opensource.org/licenses/bsd-license New BSD License
 * @package Raise.Core.Caching
 * @since 1.2
 */
class RaiseCache extends RaiseObject implements IRaiseCache {

    /**
     * Amount of seconds that this cache should live
     * @var RaiseTimeSpan
     */
    private $life;

    /**
     * A unique identifier of this cache
     * @var string
     */
    private $id;

    /**
     * Create a new RaiseCache
     * @param RaiseTimeSpan $life The time period this cache should live
     * @param string $id The unique identifier to identify this cache
     */
    function __construct($life, $id) {
        $this->life($life);
        $this->id($id);
    }

    /**
     * Get or set the period of time that this cache should live
     * @param RaiseTimeSpan $c (optional) If this parameter is passed in, it will set the new value.
     * @return RaiseTimeSpan
     */
    public function life($c = null){
        if(func_num_args() == 1){
            $this->life = $c;
        }
        return $this->life;
    }

    /**
     * Get or set the unique identifier of this cachable
     * @param string $c (optional) If this parameter is passed in, it will set the new value.
     * @return string
     */
    public function id($i = null){
        if(func_num_args() == 1){
            $this->id = $i;
        }
        return $this->id;
    }

    /**
     * Get the cache folder of phpRaise File Caching
     * @return string
     */
    public static function folder(){
        static $folder;
        if(!$folder){
            $folder = RaisePath::resolve(pathinfo(__FILE__, PATHINFO_DIRNAME) . RaisePath::directorySeparator() . '..' . RaisePath::directorySeparator() . 'cache' . RaisePath::directorySeparator());
        }
        return $folder;
    }

    /**
     * Empty the cache folder of phpRaise
     * All cache stores in the caching folder will be deleted, whether it's expired or not.
     */
    public static function clear(){
        RaiseFileSystem::emptyPath(self::folder());
    }

    /**
     * Get the RaiseFile object representing the cache store
     * @return RaiseFile
     */
    public function file(){
        if(!$this->id()){
            throw new RaiseInvalidRequestException('Cache ID is not supplied. Cache ID must be supplied before caching operations.');
        }
        static $f = null;
        if(!$f){
            $f = new RaiseFile(RaisePath::combine(self::folder(), RaiseHashDigest::sha256($this->id())));
        }
        return $f;
    }

    /**
     * Get the expiry RaiseDateTime of the casche
     * @return RaiseDateTime
     */
    public function expiry(){
        $cache = $this->file();
        if($cache->exists()){
            return $cache->getLastModified()->add($this->life());
        }else{
            return null;
        }
    }

    /**
     * Query if the cache is still available for loading
     * @return boolean
     */
    public function query(){
        $cache = $this->file();
        $loadCache = false;
        if($cache->exists()){
            $loadCache = $this->expiry()->toTimestamp() >= time();
        }
        return $loadCache;
    }
    
    /**
     * Load the cache if cache is available
     * @return string
     */
    public function load(){
        if($this->query()){
            $cache = $this->file();
            return $cache->getContent();
        }
        return null;
    }

    /**
     * Save the cache with a fresher content
     * @param string $c Content to save
     */
    public function save($c){
        $cache = $this->file();
        $cache->setContent($c);
    }

    /**
     * Clear the cache store of this object
     */
    public function delete(){
        $cache = $this->file();
        $cache->delete();
    }

}